package com.baishui.gateway;

import com.baishui.gateway.classloader.GateWayClassLoader;
import org.apache.dubbo.common.bytecode.Wrapper;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.config.bootstrap.builders.ReferenceBuilder;
import org.apache.dubbo.config.bootstrap.builders.RegistryBuilder;
import org.mybatis.spring.annotation.MapperScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.lang.reflect.Method;

//@EnableDubbo

/**
 * 相当于自动扫描 {@link org.springframework.stereotype.Component}
 */
@MapperScan("com.baishui.gateway.mapper")
@SpringBootApplication
public class GatewayApplication {
    private final static Logger log = LoggerFactory.getLogger(GatewayApplication.class);

    public static void main(String[] args) throws Exception {
        String name = "org.apache.dubbo.demo.DemoService";
        SpringApplication.run(GatewayApplication.class, args);

        GateWayClassLoader instance = GateWayClassLoader.getInstance();
        Class<?> aClass = instance.loadClass(name);

        // runWithBootstrap(aClass,instance);
//        runWithRefer(aClass, instance);
        log.error(" success ----> {}", aClass.getName());
    }


    /**
     * ????? TODO
     *
     * @param aClass
     * @param classLoader
     * @throws Exception
     */
    private static void runWithBootstrap(Class aClass, ClassLoader classLoader) throws Exception {
        // ========================= DUBBO ============================
        ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader();
        try {
            /**
             * 设置上下文classLoader
             * {@link ReferenceConfig#checkAndUpdateSubConfigs() #460} !1
             */
//            Thread.currentThread().setContextClassLoader(classLoader);
            DubboBootstrap start = DubboBootstrap.getInstance()
                    .registry(RegistryBuilder.newBuilder().address("zookeeper://127.0.0.1:2181").build())
                    .reference((ReferenceConfig<?>) ReferenceBuilder.newBuilder().interfaceClass(aClass).generic(false).build())
                    .start();

            System.out.println();

        } finally {
            Thread.currentThread().setContextClassLoader(oldContextClassLoader);
        }
    }


    private static void runWithRefer(Class aClass, ClassLoader classLoader) {
        ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader();
        try {
            Thread.currentThread().setContextClassLoader(classLoader);
            ReferenceConfig<Object> reference = new ReferenceConfig<>();
            reference.setRegistry(new RegistryConfig("zookeeper://127.0.0.1:2181"));
            reference.setInterface(aClass);
            reference.setCheck(false);
            Object o = reference.get();

            // ========================================================
            Wrapper wrapper = Wrapper.getWrapper(aClass);
            Object sayHello1 = wrapper.invokeMethod(o, "sayHello", new Class[]{aClass},
                    new Object[]{"hahahahahahah"});
            System.out.println("wrapper sayHello: " + sayHello1);


            // ========================================================
            Method sayHello = aClass.getMethod("sayHello", String.class);
            Object message = sayHello.invoke(o, "hahahahahahah");
            System.out.println("reflect sayHello: " + message);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            Thread.currentThread().setContextClassLoader(oldContextClassLoader);
        }
    }

}
